package com.boe.csb.web.controller.base;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.boe.csb.core.common.CsbConstants;
import com.boe.csb.core.common.exception.CSBErrorCode;
import com.boe.csb.core.common.exception.CSBException;
import com.boe.csb.core.common.status.PublishStatusEnum;
import com.boe.csb.core.common.utils.CsbApiCaller;
import com.boe.csb.core.common.utils.FtpUtil;
import com.boe.csb.core.dao.BoeUserFtpMapper;
import com.boe.csb.core.entity.UserInfo;
import com.boe.csb.core.entity.dto.ApiInfoDetail;
import com.boe.csb.core.entity.po.ApiCategory;
import com.boe.csb.core.entity.po.BoeApiInfo;
import com.boe.csb.core.entity.po.BoeUser;
import com.boe.csb.core.service.api.ApiCategoryService;
import com.boe.csb.core.service.api.BoeApiInfoService;
import com.boe.csb.core.service.api.BoeApiPopularService;
import com.boe.csb.core.service.csb.CsbAuditOrderService;
import com.boe.csb.core.service.csb.CsbManagerApiService;
import com.boe.csb.core.service.csb.CsbManagerOrderService;
import com.boe.csb.core.service.user.BoeUserService;
import com.boe.csb.web.controller.BaseController;
import com.boe.csb.web.model.ResultModel;
import com.google.common.collect.Lists;

/**
 * @author tianxiang.luo
 * @date 2016 - 11 - 24 上午10:41
 */
@RestController
@RequestMapping("/api/info")
public class ApiController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(ApiController.class);

    /**最大返回的历史记录数*/
    private static final int SEARCH_HISTORY_LIMIT = 6;

    @Autowired
    private BoeApiInfoService boeApiInfoService;
    @Autowired
    private BoeApiPopularService boeApiPopularService;
    @Autowired
    private BoeUserService boeUserService;
    @Autowired
    private CsbManagerApiService csbManagerApiService;
    @Autowired
    private CsbManagerOrderService csbManagerOrderService;
    @Autowired
    private ApiCategoryService apiCategoryService;
    @Autowired
    private CsbAuditOrderService csbAuditOrderService;
    @Autowired
    private BoeUserFtpMapper boeUserFtpMapper;

    /**
     * 根据 服务名或者 描述 模糊查询
     *
     * @param
     */
    @RequestMapping(value = "find", method = RequestMethod.POST)
    public ResultModel<List<BoeApiInfo>> findBoeApiInfo(@RequestParam String query, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam Integer limit) {
        return ResultModel.success(boeApiInfoService.findBoeApiInfo(query.trim(), pageNum, limit));
    }

    /**
     * 根据 服务名或者 描述 模糊查询
     *
     * @param
     */
    @RequestMapping(value = "find/count", method = RequestMethod.POST)
    public ResultModel<Integer> findBoeApiInfoCount(@RequestParam String query, HttpSession session) {
    	UserInfo userInfo = (UserInfo) session.getAttribute(USER_KEY);
    	if(userInfo != null){//更新最近搜索信息
    		boeUserService.addLatelySearch(userInfo.getUserId(), query);
    	}
        return ResultModel.success(boeApiInfoService.findBoeApiInfoCount(query.trim()));
    }
    
    /**
     * 获得历史搜索记录(默认6条)
     * @param session
     * @return
     */
    @RequestMapping(value = "find/history", method = RequestMethod.GET)
    public ResultModel<List<String>> getHistorySearch(HttpSession session){
    	UserInfo userInfo = (UserInfo) session.getAttribute(USER_KEY);
    	List<String> latelySearch = Lists.newArrayList();
    	if(userInfo != null){//查询数据库
    		latelySearch = boeUserService.queryUserLatelySearch(userInfo.getUserId());
    	}
    	
    	if(latelySearch.size() < SEARCH_HISTORY_LIMIT){//补足,查询热门服务top n
    		List<BoeApiInfo> popularApp = boeApiPopularService.queryPopularBoeApiList(1, (6 - latelySearch.size()));
    		for(BoeApiInfo apiInfo : popularApp){
    		    if(!latelySearch.contains(apiInfo.getAlias())){
                    latelySearch.add(apiInfo.getAlias());
                }

    			if(latelySearch.size() >= SEARCH_HISTORY_LIMIT){
                    break;
                }
    		}
    	}
    	
    	return ResultModel.success(latelySearch);
    }


    /**
     * 查询热门的服务
     *
     * @param pageNum 页数
     * @param limit   数据量
     * @return
     */
    @RequestMapping(value = "query/popular", method = RequestMethod.GET)
    public ResultModel<List<BoeApiInfo>> queryPopularBoeApiList(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam Integer limit) {
        return ResultModel.success(boeApiPopularService.queryPopularBoeApiList(pageNum, limit));
    }


    /**
     * 查询精品的服务
     *
     * @param pageNum 页数
     * @param limit   数据量
     * @return
     */
    @RequestMapping(value = "recommend/query", method = RequestMethod.GET)
    public ResultModel<List<BoeApiInfo>> queryRecommendBoeApiList(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam Integer limit) {
        return ResultModel.success(boeApiInfoService.queryRecommendBoeApiList(pageNum, limit));
    }

    /**
     * 添加精品服务
     *
     * @param apiId
     * @return
     */
    @RequestMapping(value = "recommend/add", method = RequestMethod.POST)
    public ResultModel<Object> addRecommendApi(@RequestParam Long apiId) {
        CSBErrorCode errCode = boeApiInfoService.addRecommend(apiId);
        return errCode == CSBErrorCode.SUCCESS ? ResultModel.success(null) : ResultModel.fail(errCode, null);
    }

    /**
     * 删除精品服务
     *
     * @param apiId
     * @return
     */
    @RequestMapping(value = "recommend/delete", method = RequestMethod.POST)
    public ResultModel<Object> delRecommendApi(@RequestParam Long apiId) {
        CSBErrorCode errCode = boeApiInfoService.delRecommand(apiId);
        return errCode == CSBErrorCode.SUCCESS ? ResultModel.success(null) : ResultModel.fail(errCode, null);
    }


    /**
     * 根据二级类目查询服务
     *
     * @param categoryId 二级类目
     * @param pageNum
     * @return
     */
    @RequestMapping(value = "query/second/list", method = RequestMethod.GET)
    public ResultModel<List<BoeApiInfo>> queryBoeApiList(@RequestParam Long categoryId, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam Integer limit) {
        return ResultModel.success(boeApiInfoService.queryBoeApiInfoList(categoryId, pageNum, limit));
    }


    /**
     * count二级类目下服务数
     *
     * @param categoryId
     * @return
     */
    @RequestMapping(value = "count/second/list", method = RequestMethod.GET)
    public ResultModel<Long> countSecondList(@RequestParam Long categoryId) {
        return ResultModel.success(boeApiInfoService.countSecondList(categoryId));
    }


    /**
     * 请求api详情页
     *
     * @param serviceId csb的服务id
     * @return
     */
    @RequestMapping(value = "detail")
    public ResultModel<ApiInfoDetail> queryApiInfoAndUserInfo(HttpSession session, @RequestParam Long serviceId) {
        UserInfo userInfo = fetchUserInfo(session);
        String loginId = null;
        BoeApiInfo boeApiInfo = boeApiInfoService.queryBoeApiInfo(serviceId);
        if (null == boeApiInfo) {
            logger.error("can't find server by id:{}.", serviceId);
            return ResultModel.fail(CSBErrorCode.NOT_FOUND, "查找不到对应的服务信息");
        }
        //如果是没登入则根据api详情的状态来判断是否可查看
        if (userInfo == null) {
            if (!(PublishStatusEnum.ACTIVE.getStatus().equals(boeApiInfo.getApiStatus()) || PublishStatusEnum.STOP.getStatus().equals(boeApiInfo.getApiStatus()))) {
                logger.error("service status is not active or stop,cant show it:{}.", serviceId);
                return ResultModel.fail(CSBErrorCode.NOT_FOUND, "服务可能已经被删除,无法显示");
            }
        } else {
            loginId = String.valueOf(userInfo.getUserId());
            //如果登入了 服务是发布者||管理员想查看
            if (userInfo.getIsAdmin() != null && (!userInfo.getIsAdmin() && !csbManagerApiService.checkServiceBelongUser(serviceId, loginId))) {
                if (!(PublishStatusEnum.ACTIVE.getStatus().equals(boeApiInfo.getApiStatus()) || PublishStatusEnum.STOP.getStatus().equals(boeApiInfo.getApiStatus()))) {
                    logger.error("service status is not active or stop,cant show it:{}.", serviceId);
                    return ResultModel.fail(CSBErrorCode.NOT_FOUND, "服务可能已经被删除,无法显示");
                }
            }
        }

        //获取api的订阅数量
        int subCount = boeApiPopularService.getSubscribeCount(serviceId);
        Long userId = boeApiInfo.getUserId();
        ApiInfoDetail apiInfoDetail = new ApiInfoDetail();
        //取出本地用户的数据  ,true去掉敏感信息
        BoeUser boeUser = boeUserService.queryBoeUser(userId, true);

        Long categoryId = boeApiInfo.getCategoryId();
        ApiCategory apiCategory = apiCategoryService.queryCategoryById(categoryId);
        String categoryName = apiCategory.getName();
        Map<String,String> map = apiCategoryService.getCatagoryInfo(apiCategory);
        //返回类目信息
        apiInfoDetail.setCategory(JSON.toJSONString(map));
        
        apiInfoDetail.setCategoryName(categoryName);
        apiInfoDetail.setServicePic(boeApiInfoService.getImgPathByService(boeApiInfo));
        //取出csb的接口信息
        JSONObject apiInfo = csbManagerApiService.findSingleService(CsbApiCaller.CSB_ADMIN_ID, serviceId).getData();
        //获取服务名
        String serviceName = apiInfo.getJSONObject("service").getString("serviceName");
        apiInfoDetail.setBoeUser(boeUser);
        apiInfoDetail.setBoeApiInfo(apiInfo);
        apiInfoDetail.setIsSubscribe(csbManagerOrderService.queryOrderStatus(loginId, serviceId,serviceName));
        apiInfoDetail.setSubScribeCount(subCount);
        
        //根据用户ID和服务ID，及类型获取logo的id
        Long serviceLogoID = boeUserFtpMapper.selectFtpID(userId, boeApiInfo.getCsbApiId());
        apiInfoDetail.setServiceLogoID(serviceLogoID);

        //获取服务调用req
        apiInfoDetail.setBoeApiAddress(CsbConstants.CSB_API_ADDRESS);
        return ResultModel.success(apiInfoDetail);
    }

    /**
     * 下载sdk
     * FIXME 是否控制调用频率
     *
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "getsdk", method = RequestMethod.GET)
    public void downloadSdk(HttpServletResponse response, @RequestParam String type) throws IOException {

        String sdkName = boeApiInfoService.getSdkName(type);
        if (sdkName == null) {
            logger.error("don't have sdk of type:{}.", type);
            throw new CSBException(CSBErrorCode.PARAM_ERR, "暂时不支持该语言类型");
        }

        //response.setContentType(getServletContext().getMimeType(filename));
        //设置Content-Disposition  
        response.setHeader("Content-Disposition", "attachment;filename=" + sdkName);

        byte[] bytes = FtpUtil.download("sdk", sdkName);//FIXME sdk路径暂时写死
        OutputStream os = response.getOutputStream();
        InputStream in = new ByteArrayInputStream(bytes);
        int len = 0;
        byte[] buf = new byte[1024];
        while ((len = in.read(buf, 0, 1024)) != -1) {
            os.write(buf, 0, len);
        }
        os.flush();
    }

}
